#include "AppMenuItem.h"

#include <core/ImageMgr.h>
#include <widgets/SImageButton.h>

#include <QBoxLayout>
#include <QJsonObject>
#include <QLabel>
#include <QMouseEvent>
#include <QPushButton>
#include <QStylePainter>
#include <QTimer>

#include "../CMD/CmdMgr.h"
#include "AppMenuPanel.h"

// QT在重新排版时，会导致onhover判断出现一些问题，应该想办法避免relayout时，已有控件的位置变动
bool AppMenuItem::s_notifying = false;

AppMenuItem::AppMenuItem(QJsonObject* obj, QWidget* parent) : QWidget(parent) {
  construct(obj);
  setMouseTracking(true);
}

AppMenuItem::AppMenuItem(int cmdId, QWidget* parent) : QWidget(parent) {
  construct(cmdId);
  setMouseTracking(true);
}

bool AppMenuItem::isRedPoint() {
  Command* cmd = CmdMgr::instance().command(m_item.cmdId);
  if (cmd) {
    return cmd->isRedPoint();
  }
  return false;
}

bool AppMenuItem::isEnabled() {
  Command* cmd = CmdMgr::instance().command(m_item.cmdId);
  return cmd && !cmd->module().isEmpty();
}

void AppMenuItem::leaveEvent(QEvent* event) {
  if (s_notifying)  // during relayout!!!
    return;
  m_hover = false;
  onHoverChanged();
}

void AppMenuItem::mouseMoveEvent(QMouseEvent* e) {
  if (s_notifying) return;
  QRect hoverRect = rect();
  hoverRect.adjust(0, 6, 0, -6);
  bool hover = hoverRect.contains(e->pos());
  if (hover != m_hover) {
    m_hover = hover;
    onHoverChanged();
  }
}

void AppMenuItem::mouseReleaseEvent(QMouseEvent* e) {
  QRect hoverRect = rect();
  hoverRect.adjust(0, 6, 0, -6);
  bool clicked = hoverRect.contains(e->pos());
  if (clicked) {
    m_hover = false;
    onHoverChanged();
    AppMenuPanel::g_menuPanel()->hide();
    QTimer::singleShot(0,
                       [this]() { CmdMgr::instance().execCmd(m_item.cmdId); });
  }
}

void AppMenuItem::paintEvent(QPaintEvent* event) {
  QStylePainter painter(this);

  painter.setPen(Qt::transparent);
  painter.setRenderHint(QPainter::Antialiasing);  // 抗锯齿

  if (m_hover && isEnabled()) {
    QRect hoverRect = rect();
    hoverRect.adjust(0, 6, 0, -6);
    // painter.fillRect(hoverRect, QColor(26, 79, 71));
    painter.setBrush(QBrush(QColor(11, 77, 82)));
    painter.drawRoundedRect(hoverRect, 2, 2);
  } else if (!isEnabled()) {
    QRect hoverRect = rect();
    hoverRect.adjust(0, 6, 0, -6);
    // painter.fillRect(hoverRect, Qt::gray);
    painter.setBrush(QBrush(Qt::gray));
    painter.drawRoundedRect(hoverRect, 2, 2);
  }

  if (m_item.tag != Command::CmdTag::kNone) {
    SImage* image = ImgMgr::instance().image(
        m_item.tag == Command::CmdTag::kHot ? "guiframe_catalogue_hot"
                                            : "guiframe_catalogue_new",
        WidgetStatus::kNormal, devicePixelRatioF());
    if (image) {
      QRect titleFrame = m_labelTitle->frameGeometry();
      int posX = titleFrame.right() - 5;

      painter.setRenderHint(QPainter::SmoothPixmapTransform);  // 处理图片失真
      painter.drawImage(posX, 0, *image);
    }
  }
}

void AppMenuItem::construct(int cmdId) {
  m_item.tag = Command::CmdTag::kNone;
  m_item.cmdId = cmdId;
  ;
  Command* cmd = CmdMgr::instance().command(m_item.cmdId);
  if (cmd) {
    m_item.tag = cmd->tag();
    m_item.abbr = cmd->abbr();
    m_item.title = cmd->name();
  } else {
    Q_ASSERT_X(false, "Command can't be found!",
               QString::number(cmdId).toStdString().c_str());
    return;
  }

  setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
  setFixedSize(146, 42);
  m_layout = new QHBoxLayout();
  m_layout->setContentsMargins(5, 0, 1, 0);
  m_layout->setSpacing(0);

  QString title = "<p style=\"font-size:12px; color:#FFEBC8\">%1</p>";
  title = title.arg(m_item.title);
  m_labelTitle = new QLabel(title);
  // so I can get the mousemove event when mouse is move to it very quickly!
  m_labelTitle->setAttribute(Qt::WA_TransparentForMouseEvents);
  m_layout->addWidget(m_labelTitle);

  m_layout->addStretch();

  QString abbr = "<p style=\"font-size:12px; color:#458C81\">%1</p>";
  abbr = abbr.arg(m_item.abbr);
  m_labelAbbr = new QLabel(abbr);
  m_labelAbbr->setAttribute(Qt::WA_TransparentForMouseEvents);
  m_layout->addWidget(m_labelAbbr);

  // TODO: check if can add
  m_btn = new SImageButton(this, "guiframe_catalogue_add");
  m_btn->setVisible(false);
  m_btn->setFixedSize(24, 24);
  connect(m_btn, &SImageButton::clicked, this, &AppMenuItem::onBtnClicked);

  m_layout->addWidget(m_btn);

  m_spacer = new QSpacerItem(8, 2, QSizePolicy::Fixed, QSizePolicy::Preferred);

  setLayout(m_layout);
}

void AppMenuItem::construct(QJsonObject* obj) {
  if (obj == nullptr) return;

  m_item.cmdId = obj->value("id").toInt();
  construct(m_item.cmdId);
}

void AppMenuItem::onHoverChanged() {
  s_notifying = true;
  if (m_hover) {
    if (AppMenuPanel::g_menuPanel()->hasAddedToFav(m_item.cmdId)) {
      m_btn->setImgId(m_isInFav ? "guiframe_catalogue_delete"
                                : "guiframe_catalogue_added");
      m_btn->setVisible(true);
    } else if (AppMenuPanel::g_menuPanel()->canAddToFav()) {
      m_btn->setImgId("guiframe_catalogue_add");
      m_btn->setVisible(true);
    }

    m_labelAbbr->setVisible(false);
    m_layout->addSpacerItem(m_spacer);
  } else {
    m_btn->setVisible(false);
    m_labelAbbr->setVisible(true);
    m_layout->removeItem(m_spacer);
  }

  update();
  AppMenuPanel::g_menuPanel()->onItemHoverChanged(m_item.cmdId, m_hover);
  s_notifying = false;
}

void AppMenuItem::onBtnClicked() {
  bool add = !AppMenuPanel::g_menuPanel()->hasAddedToFav(m_item.cmdId);
  AppMenuPanel::g_menuPanel()->onItemAction(m_item.cmdId, add);
  m_btn->setImgId(add ? (m_isInFav ? "guiframe_catalogue_delete"
                                   : "guiframe_catalogue_added")
                      : "guiframe_catalogue_add");
}
